import * as THREE from "three";
import nipplejs from "nipplejs";
import { Capsule } from "three/examples/jsm/math/Capsule";
import { libraryState } from ".";
import * as TWEEN from "@tweenjs/tween.js";
import { JoyStick } from "../joystick/joystick";
import { defaultSetting } from "@/config";
import { miniMapObj } from "@/components/miniMap/MiniMap";

export class Player {
  scene: any;
  camera: any;
  octree: any;
  mesh: any;
  height: number = 1; //可以控制初始化视角高低
  offsetY: number = 0; //capsule的y轴偏移量 16
  radius: number = 0.25;
  capsule!: Capsule;
  // speed: number = 0.2;
  speed: number = 0.005; //使用自定义计时器
  forwardSpeed: number = 0; // 前进速度
  translateSpeed: number = 0; // 平移速度
  forwardDirection: any = new THREE.Vector3(0, 0, -1); // 正面方向
  translateDirection: any = new THREE.Vector3(0, 0, 0); // 侧边方向
  speedVel: any = new THREE.Vector3(0, this.offsetY, 0); //capsule的位置
  onFloor: boolean = true; //是否上移
  // gravity: number = 1; //重力
  gravity: number = 0.98; //重力
  type: number = 1; //1第一人称，2第三人称
  time: number = 0; //使用自定义计时器

  constructor(scene: any, camera: any, octree: any) {
    this.scene = scene;
    this.camera = camera;
    this.octree = octree;
    this.init();
  }

  init() {
    //胶囊体，用于碰撞检测，Capsule不是一个几何体
    //this.capsule位置方向大小设置很重要，this.height要将其底部与场景中其他几何体的基准线对齐
    console.log(
      "defaultSetting.defaultPosition",
      defaultSetting.defaultPosition
    );

    const position = defaultSetting.defaultPosition.clone();
    this.capsule = new Capsule(
      position, //第一个端点
      new THREE.Vector3(position.x, position.y + this.height, position.z), //第二个端点
      this.radius //半径
    );
    this.capsule.translate(new THREE.Vector3(0, position.y, 0)); //沿着指定方向平移,返回空间时不同楼层需要设置不同高度

    // console.log("this.capsule", this.capsule);

    this.mesh = new THREE.Mesh(
      new THREE.CapsuleGeometry(this.radius, 1),
      new THREE.MeshNormalMaterial()
    );
    this.mesh.name = "player";
    this.mesh.rotation.order = "YXZ";
    this.scene.add(this.mesh);
    if (libraryState.isMobile) {
      this.addHandler();
    } else {
      this.addkeyBoard();
    }
    this.sync();
  }
  clear() {
    this.scene.remove(this.mesh);
  }
  sync() {
    const end = this.capsule.end.clone();
    // end.y -= this.radius
    this.mesh.position.copy(end);
  }
  addkeyBoard() {
    document.onkeydown = (e: any) => {
      if (e.key === "q") {
        //切换视角
        this.type = this.type === 1 ? 2 : 1;
      } else {
        this.keyBoardEvent(e, "down");
      }
    };
    document.onkeyup = (e: any) => {
      if (e.key !== "q") this.keyBoardEvent(e, "up");
      console.log("当前位置", this.mesh.position);
    };
  }
  addHandler() {
    let that = this;
    libraryState.joyStick = new JoyStick({
      onMove: function (forward, turn) {
        turn = -turn;
        if (Math.abs(forward) < 0.3) forward = 0;
        if (Math.abs(turn) < 0.1) turn = 0;
        that.forwardSpeed = -forward * 0.008;
        that.translateSpeed = -turn * 0.008;
        // console.log(that.forwardSpeed,that.translateSpeed);
        // console.log('相机位置',that.camera.position);
      },
    });
  }
  addJoystick() {
    // 创建Joystick
    var options: any = {
      zone: document.getElementById("joystickContainer"), // 指定Joystick的DOM容器
      mode: "static", // 'dynamic', 'static', 'semi'
      position: { left: "50%", top: "50%" }, // Joystick的位置
      color: "red", // Joystick的颜色
    };
    var manager = nipplejs.create(options);

    // 监听Joystick的移动事件
    manager.on("move", function (evt, data) {
      let distance = data.distance, // 拖动的距离
        angle = data.angle.radian; // 拖动的角度，以弧度为单位

      // 根据Joystick的移动来更新Three.js相机或对象的位置
      // 例如，可以根据距离和角度来计算相机的新位置
      // let speedFactor=0.01;
      // camera.position.x += Math.cos(angle) * distance * speedFactor;
      // camera.position.z += Math.sin(angle) * distance * speedFactor;
    });
  }
  keyBoardEvent(e, type) {
    if (e.keyCode == 27) {
      //esc
      document.exitPointerLock();
      return;
    }
    switch (e.keyCode) {
      case 38: // up
      case 87: // w
        if (type == "down") {
          this.forwardSpeed = -this.speed;
        } else {
          this.forwardSpeed = 0;
        }
        break;
      case 37: // left
      case 65: // a
        if (type == "down") {
          this.translateSpeed = -this.speed;
        } else {
          this.translateSpeed = 0;
        }
        break;
      case 40: // down
      case 83: // s
        if (type == "down") {
          this.forwardSpeed = this.speed;
        } else {
          this.forwardSpeed = 0;
        }
        break;
      case 39: // right
      case 68: // d
        if (type == "down") {
          this.translateSpeed = this.speed;
        } else {
          this.translateSpeed = 0;
        }
        break;
        case 32: // 空格
        if (type == "up" && !this.speedVel.y) {
          this.speedVel.y = 0.06;
          this.time = 0;
        } else {
          this.speedVel.y = 0;
        }
        break;
    }
  }
  update(delta) {
    this.handleDirection();
    this.handleMove(delta);
    this.updateControls();
  }
  animateSpeed() {
    return new Promise((resolve) => {
      const time = 3000;
      let startPosition = new THREE.Vector3();
      startPosition.copy(this.mesh.position);
      libraryState.tweenPosition = new TWEEN.Tween(startPosition)
        .to(libraryState.spriteTarget, time)
        .easing(TWEEN.Easing.Quadratic.InOut) // 使用缓动函数使过渡更加平滑
        .onUpdate(() => {
          // 计算平移量
          const translationVector = new THREE.Vector3().subVectors(
            startPosition,
            this.capsule.end
          );
          translationVector.y = 0;
          this.capsule.translate(translationVector);
          this.handleCollider();
          this.sync();
          this.check();
          this.updateControls();
        })
        .onComplete(() => {
          console.log("移动完成", startPosition);
          libraryState.spriteTarget = undefined;
          resolve(true);
        })
        .start();
    });
  }
  async handleMove(deltaTime: number) {
    let damping = Math.exp(-4 * deltaTime) - 1; //阻尼
    if (libraryState.spriteTarget) {
      await this.animateSpeed();
    } else {
      // const speedDelta = deltaTime * (this.onFloor ? 25 : 8);
      // const forwardSpeed = this.forwardDirection.multiplyScalar(
      //   this.forwardSpeed * speedDelta
      // );
      // const translateSpeed = this.translateDirection.multiplyScalar(
      //   this.translateSpeed * speedDelta
      // );
      // if (!this.onFloor) {
      //   this.speedVel.y -= (this.gravity + this.offsetY) * deltaTime;
      //   damping *= 0.1;
      //   this.speedVel.addScaledVector(this.speedVel, damping);
      // }
      // 自定义计时器
      const direction = this.forwardDirection.clone();
      const forwardSpeed = direction.multiplyScalar(
        this.forwardSpeed * deltaTime
      );
      const translateSpeed = this.translateDirection.multiplyScalar(
        this.translateSpeed * deltaTime
      );
      const mulitySpeed = forwardSpeed.add(translateSpeed);
      // console.log('胶囊',forwardSpeed, translateSpeed,mulitySpeed);

      this.speedVel.x = mulitySpeed.x;
      this.speedVel.z = mulitySpeed.z;
      if (!this.onFloor) {
        this.speedVel.y -= this.gravity * this.time * 0.01;
        this.time += deltaTime * 0.003;
      }
      this.capsule.translate(this.speedVel);
      this.handleCollider(); //碰撞检测
      this.sync(); //同步mesh胶囊
      this.check(); //回归中心点
      // 同步到缩略图上
      this.handleMiniMapMove();
      this.handleMiniMapRoate();
    }
  }
  check(isDefault?: boolean) {
    if (this.mesh.position.y < -100 || isDefault) {
      const position = defaultSetting.defaultPosition.clone();
      //恢复初始位置
      this.capsule = new Capsule(
        position,
        new THREE.Vector3(position.x, this.height, position.y),
        this.radius
      );
      this.speedVel.set(0, 0, 0);
      this.sync();
    }
  }
  handleCollider() {
    //检查场景空间和胶囊的碰撞
    const result = this.octree.capsuleIntersect(this.capsule);
    this.onFloor = false;
    // if (result) {
    //   const { normal, depth } = result;
    //   this.onFloor = normal.y > 0; //检查碰撞法线的 y 分量，确定是否在地面上
    //   if (!this.onFloor) {
    //     // 使用反射公式，通过 dot 乘法计算反射向量,这里表示将1缩放到2的长度
    //     this.speedVel.addScaledVector(
    //       result.normal, //1
    //       -result.normal.dot(this.speedVel) //2
    //     );
    //   }
    //   this.capsule.translate(normal.multiplyScalar(depth)); //实现不同平面的行走
    // }
    //使用自定义计时器
    if (result) {
      const { normal, depth } = result;
      this.onFloor = normal.y > 0;

      if (!this.onFloor) {
        this.speedVel.addScaledVector(
          result.normal, //碰撞平面法向量，指向离开碰撞表面的方向
          -result.normal.dot(this.speedVel) //运动方向和取反的法向量之间的投影（夹角常量）
        ); //实现碰撞面反弹的效果，result.normal方向，-result.normal.dot(this.speedVel)速度
      } else {
        this.time = 0;
        this.speedVel.y = 0;
      }

      //进行爬坡和下坡移动 沿着法线 >
      this.capsule.translate(normal.multiplyScalar(depth));
    }
  }
  handleDirection() {
    const camera = this.camera;
    const yRadian = camera.rotation.y;
    this.forwardDirection.x = Math.sin(yRadian);
    this.forwardDirection.z = Math.cos(yRadian);
    this.translateDirection.x = Math.sin(yRadian + Math.PI * 0.5);
    this.translateDirection.z = Math.cos(yRadian + Math.PI * 0.5);
  }
  updateControls() {
    const position = this.mesh.position.clone();
    const direction = this.forwardDirection.clone();
    const offsetPosition = new THREE.Vector3();
    if (this.type === 1) {
      offsetPosition.copy(position);
      if (offsetPosition.y > 1.5) {
        offsetPosition.y += 0.5;
      } else {
        offsetPosition.y = 1.5;
      }
    } else if (this.type === 2) {
      offsetPosition.copy(position.sub(direction.multiplyScalar(-1)));
      offsetPosition.y += 1;
    }
    this.camera.position.copy(offsetPosition);
  }
  handleMiniMapMove() {
    //1、移动方向
    // const defaultDirection = new THREE.Vector3(0, 0, -1);
    // const curDirection = new THREE.Vector3(this.speedVel.x, 0, this.speedVel.z);
    // let curDegrees = 0;
    // const dotRes = defaultDirection.dot(curDirection);
    // // 计算夹角的余弦值
    // const cosTheta =
    //   dotRes / (defaultDirection.length() * curDirection.length());
    // // 计算夹角的弧度
    // const angleRadians = Math.acos(cosTheta);
    // // 将弧度转换为角度
    // const angleDegrees = THREE.MathUtils.radToDeg(angleRadians);
    // if (isNaN(angleDegrees)) {
    //   return;
    // } else {
    //   if (this.speedVel.x > 0) {
    //     curDegrees = angleDegrees;
    //   } else {
    //     curDegrees = -angleDegrees;
    //   }
    // }
    // miniMapObj.point.degrees = curDegrees;
    //2、位置
    let scale = miniMapObj.scale;
    const { x, y, z } = this.capsule.end;
    // const offset2D = Math.sqrt(x * x + z * z);//移动距离
    miniMapObj.point.position = {
      x: miniMapObj.default[0] + x * scale,
      y: miniMapObj.default[1] + z * scale,
    };
  }
  handleMiniMapRoate() {
    // 旋转方向
    // 获取相机绕Y轴的旋转角度（弧度）
    const cameraRotationY = this.camera.rotation.y;
    const angleDegrees = THREE.MathUtils.radToDeg(cameraRotationY);
    miniMapObj.point.degrees = -angleDegrees;
  }
}
